#include "GamePlayLayer.h"
#include "Utils.h"
#include "SimpleAudioEngine.h"
#include "GameConst.h"

#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
#define MAIN_FONT "Marker Felt"
#else
#define MAIN_FONT "fonts/Feast of Flesh BB.ttf"
#endif

GamePlayLayer::GamePlayLayer()
{

}

GamePlayLayer::~GamePlayLayer()
{
}

bool GamePlayLayer::init(){
	scheduleUpdate();
	CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,2,true);

	level = 0;
	leftOperator = 0;
	rightOperator = 0;
	result = 0;
	isCorrect = false;

	createMenu();
	createGameControls();
    preloadSound();

	return true;
}

void GamePlayLayer::update(float delta){
	if(GameManager::getInstance()->score > 0 && state == GS_PLAY){
		remainTime -= delta;
		if(remainTime < 0){
			Utils::playEffect("Fail");
			setState(GS_GAME_OVER);
		}
		timeSprite->setScaleX(remainTime);
	}
}

bool GamePlayLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
	return true;
}

void GamePlayLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent){
}


void GamePlayLayer::draw(){
}

void GamePlayLayer::createGameControls(){
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
	float horPadding = 20;
	float buttonBottomPading = 50;

	falseButton = CCControlButton::create();
	falseButton->setBackgroundSpriteFrameForState(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("FalseButton.png"), CCControlStateNormal);
	falseButton->setAdjustBackgroundImage(false);
	falseButton->setPosition(ccp(horPadding + falseButton->boundingBox().size.width/2, buttonBottomPading + falseButton->boundingBox().size.height/2));
	falseButtonOriginLocation = falseButton->getPosition();
	falseButton->setVisible(false);
	falseButton->addTargetWithActionForControlEvents(this, cccontrol_selector(GamePlayLayer::falseButtonTouched), CCControlEventTouchUpInside);
	addChild(falseButton);

	trueButton = CCControlButton::create();
	trueButton->setBackgroundSpriteFrameForState(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("TrueButton.png"), CCControlStateNormal);
	trueButton->setAdjustBackgroundImage(false);
	trueButton->setPosition(ccp(visibleSize.width - horPadding - trueButton->boundingBox().size.width/2, buttonBottomPading + trueButton->boundingBox().size.height/2));
	trueButtonOriginLocation = trueButton->getPosition();
	trueButton->setVisible(false);
	trueButton->addTargetWithActionForControlEvents(this, cccontrol_selector(GamePlayLayer::trueButtonTouched), CCControlEventTouchUpInside);
	addChild(trueButton);

	timeSprite = CCSprite::createWithSpriteFrameName("TimeBar.png");
	timeSprite->setAnchorPoint(ccp(0, 0.5));
	timeSprite->setPosition(ccp(0, visibleSize.height - timeSprite->boundingBox().size.height/2));
	timeSprite->setVisible(false);
	addChild(timeSprite);
    
    float centerYOfTwoLabel = (timeSprite->boundingBox().getMinY() + falseButton->boundingBox().getMaxY())/2;

	calculationLabel = CCLabelTTF::create("1 + 3","", 60);
	calculationLabel->setColor(ccc3(222, 222, 222));
	calculationLabel->setPosition(ccp(visibleSize.width/2, centerYOfTwoLabel + 30));
	calculationLabel->setVisible(false);
	addChild(calculationLabel);

	resultLabel = CCLabelTTF::create("= 5","", 60);
	resultLabel->setColor(ccc3(222, 222, 222));
	resultLabel->setPosition(ccp(visibleSize.width/2, centerYOfTwoLabel - 30));
	resultLabel->setVisible(false);
	addChild(resultLabel);

	failSprite = CCSprite::createWithSpriteFrameName("Fail.png");
	failSprite->setPosition(ccp(resultLabel->getPositionX(), (resultLabel->getPositionY() + calculationLabel->getPositionY())/2));
	failSprite->setVisible(false);
	addChild(failSprite);
}

void GamePlayLayer::createMenu(){
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	backgroundSprite = CCSprite::createWithSpriteFrameName("BlackBoardBackground.png");
	backgroundSprite->setScale(1.2f);
	backgroundSprite->setPosition(ccp(visibleSize.width/2, visibleSize.height/2 + 40));
	addChild(backgroundSprite);

	int topPadding = 40;

	scoreLabel = CCLabelTTF::create("",MAIN_FONT, 24);
	scoreLabel->setColor(ccc3(222, 222, 222));
	scoreLabel->setPosition(ccp(80, visibleSize.height - topPadding));
	scoreOriginLocation = scoreLabel->getPosition();
	addChild(scoreLabel);

	highScoreLabel = CCLabelTTF::create("",MAIN_FONT, 24);
	highScoreLabel->setColor(ccc3(222, 222, 222));
	highScoreLabel->setPosition(ccp(visibleSize.width - 100, visibleSize.height - topPadding));
	highScoreOriginLocation = highScoreLabel->getPosition();
	addChild(highScoreLabel);

	int leftPadding = 30;

	replayButton = CCControlButton::create();
	replayButton->setBackgroundSpriteFrameForState(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("PlayButton.png"), CCControlStateNormal);
	replayButton->setAdjustBackgroundImage(false);
	replayButton->setPosition(ccp(leftPadding + replayButton->boundingBox().size.width/2, visibleSize.height/2 - 60));
	replayButton->addTargetWithActionForControlEvents(this, cccontrol_selector(GamePlayLayer::replayButtonTouched), CCControlEventTouchUpInside);
	addChild(replayButton);

	highScoreButton = CCControlButton::create();
	highScoreButton->setBackgroundSpriteFrameForState(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("HighscoreButton.png"), CCControlStateNormal);
	highScoreButton->setAdjustBackgroundImage(false);
	highScoreButton->setPosition(ccp(visibleSize.width - leftPadding - replayButton->boundingBox().size.width/2, replayButton->getPositionY()));
	highScoreButton->addTargetWithActionForControlEvents(this, cccontrol_selector(GamePlayLayer::highScoreButtonTouched), CCControlEventTouchUpInside);
	addChild(highScoreButton);

	voteButton = CCControlButton::create();
	voteButton->setBackgroundSpriteFrameForState(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("RateButton.png"), CCControlStateNormal);
	voteButton->setAdjustBackgroundImage(false);
	voteButton->setPosition(ccp(visibleSize.width/2, replayButton->getPositionY()  + 60));
	voteButton->addTargetWithActionForControlEvents(this, cccontrol_selector(GamePlayLayer::voteButtonTouched), CCControlEventTouchUpInside);
	addChild(voteButton);

	bigTextLabel = CCLabelTTF::create("", MAIN_FONT, 40);
	bigTextLabel->setString("Math Racing Go");
	bigTextLabel->setPosition(ccp(visibleSize.width/2, replayButton->getPositionY() + 140));
	bigTextLabel->setColor(ccc3(222, 222, 222));
	addChild(bigTextLabel);
}

void GamePlayLayer::showMenu(int menuType){
	replayButton->setVisible(true);
	highScoreButton->setVisible(true);
	voteButton->setVisible(true);
	bigTextLabel->setVisible(true);

	if(menuType == MT_GAMEOVER)
		bigTextLabel->setString("Game Over");
	else if(menuType == MT_START){
		bigTextLabel->setString("Math Racing");
	}
}

void GamePlayLayer::hideMenu(){
	replayButton->setVisible(false);
	highScoreButton->setVisible(false);
	voteButton->setVisible(false);
	bigTextLabel->setVisible(false);
    Utils::hideAd();
}

void GamePlayLayer::showGameControls(bool isShowGameControls){
	trueButton->setVisible(isShowGameControls);
	falseButton->setVisible(isShowGameControls);
	timeSprite->setVisible(isShowGameControls);
	calculationLabel->setVisible(isShowGameControls);
	resultLabel->setVisible(isShowGameControls);
	if(isShowGameControls == false){
		failSprite->setVisible(false);
		trueButton->setPosition(trueButtonOriginLocation);
		falseButton->setPosition(falseButtonOriginLocation);
	}
}

void GamePlayLayer::replayButtonTouched(CCObject* sender, CCControlEvent event){
	Utils::playEffect("Wing");
	setState(GS_PLAY);
}

void GamePlayLayer::highScoreButtonTouched(CCObject* sender, CCControlEvent event){
	Utils::playEffect("Wing");
	Utils::showLeaderboards();
}

void GamePlayLayer::voteButtonTouched(CCObject* sender, CCControlEvent event){
	Utils::playEffect("Wing");
	Utils::rateApp();
}

void GamePlayLayer::trueButtonTouched(CCObject* sender, CCControlEvent event){
	if(state == GS_PLAY){
		if(isCorrect){
			GameManager::getInstance()->score++;
			newQuestion();
			Utils::playEffect("Point");
		}
		else{
			Utils::playEffect("Fail");
			setState(GS_GAME_OVER);
		}
	}
}

void GamePlayLayer::falseButtonTouched(CCObject* sender, CCControlEvent event){
	if(state == GS_PLAY){
		if(isCorrect == false){
			GameManager::getInstance()->score++;
			newQuestion();
			Utils::playEffect("Point");
		}
		else{
			Utils::playEffect("Fail");
			setState(GS_GAME_OVER);
		}
	}
}

void GamePlayLayer::setState(int state){
	this->state = state;
	switch (state)
	{
	case GS_PLAY:
		hideMenu();
		showGameControls(true);
		resetGame();
		break;

	case GS_MENU_START:
		changeToMenuState();
		break;

	case GS_GAME_OVER:
		changeToGameOverState();
        Utils::showAd();
		break;
	}
}

void GamePlayLayer::changeToGameOverState(){
	CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();

	failSprite->setVisible(true);
	failSprite->setScale(3);
	CCScaleTo* scaleAction = CCScaleTo::create(0.2, 1);
	failSprite->runAction(scaleAction);

	CCMoveTo* scoreMoveTo = CCMoveTo::create(0.2, ccp(visibleSize.width/2, visibleSize.height/2 - 30));
	CCScaleTo* scoreScaleTo = CCScaleTo::create(0.2, 2);
	scoreLabel->runAction(scoreMoveTo);
	scoreLabel->runAction(scoreScaleTo);

	CCMoveTo* highScoreMoveTo = CCMoveTo::create(0.2, ccp(visibleSize.width/2, visibleSize.height/2 - 90));
	CCScaleTo* highScoreScaleTo = CCScaleTo::create(0.2, 2);
	highScoreLabel->runAction(highScoreMoveTo);
	highScoreLabel->runAction(highScoreScaleTo);

	CCMoveBy* buttonMoveByAction = CCMoveBy::create(0.2, ccp(0, -200));
	trueButton->runAction(buttonMoveByAction);

	CCMoveBy* buttonMoveByAction2 = CCMoveBy::create(0.2, ccp(0, -200));
	falseButton->runAction(buttonMoveByAction2);

	scheduleOnce(schedule_selector(GamePlayLayer::changeToGameMenuSchedule), 2);

	// score
	GameManager* gameManager = GameManager::getInstance();
	if(gameManager->score > gameManager->highScore){
		gameManager->highScore = gameManager->score;
		gameManager->saveHighScore(gameManager->highScore);
	}
    Utils::updateTopScoreLeaderboard(gameManager->score);
}

void GamePlayLayer::changeToMenuState(){
	showMenu(MT_GAMEOVER);
	showGameControls(false);

	// animate score label
	CCMoveTo* scoreMoveTo = CCMoveTo::create(0.2, scoreOriginLocation);
	CCScaleTo* scoreScaleTo = CCScaleTo::create(0.2, 1);
	scoreLabel->runAction(scoreMoveTo);
	scoreLabel->runAction(scoreScaleTo);

	CCMoveTo* highScoreMoveTo = CCMoveTo::create(0.2, highScoreOriginLocation);
	CCScaleTo* highScoreScaleTo = CCScaleTo::create(0.2, 1);
	highScoreLabel->runAction(highScoreMoveTo);
	highScoreLabel->runAction(highScoreScaleTo);
}

void GamePlayLayer::preloadSound(){
	Utils::preloadSound("Fail");
	Utils::preloadSound("Point");
	Utils::preloadSound("Wing");
}

void GamePlayLayer::generateNewQuestion(){

	int maxNumber = 0;

	switch (level)
	{
	case 0:
		maxNumber = 5;
		break;

	case 1:
		maxNumber = 10;
		break;

	case 2:
		maxNumber = 20;
		break;

	default:
		maxNumber = 100;
		break;
	}
	

	leftOperator = 1 + rand()%maxNumber;
	rightOperator = 1 + rand()%maxNumber;
	int sum = leftOperator + rightOperator;
	result = sum;

	int incorrectRange = maxNumber*2/3;//2*(sum/3);
	if(incorrectRange == 0){
		incorrectRange = 1;
	}

	int resultInt = rand()%2;

	if(resultInt == 0){
		isCorrect = false;

		int incorrectRandom = 1 + rand()%incorrectRange;
		result += incorrectRandom;

		if(result < 0){
			result = 0;
		}
	}
	else{
		isCorrect = true;
	}
}

void GamePlayLayer::newQuestion(){

	int score = GameManager::getInstance()->score;

	if(score < 10){
		level = 0;
	}
	else if(score < 30){
		level = 1;
	}
	else if(score < 70){
		level = 2;
	}
	else{
		level = 3;
	}

	generateNewQuestion();
	updateScoreUi();

	char displayText[16] = {0};

	sprintf(displayText, "%d + %d", leftOperator, rightOperator);
	calculationLabel->setString(displayText);
	
	sprintf(displayText, "= %d", result);
	resultLabel->setString(displayText);

	remainTime = 1;
}

void GamePlayLayer::updateScoreUi(){
	char str[32] = {0};

	sprintf(str, "Score: %d", GameManager::getInstance()->score);
	scoreLabel->setString(str);

	sprintf(str, "High score: %d", GameManager::getInstance()->highScore);
	highScoreLabel->setString(str);
}

void GamePlayLayer::resetGame(){
	GameManager::getInstance()->score = 0;
	newQuestion();
	remainTime = 1;
	timeSprite->setScaleX(remainTime);
}

void GamePlayLayer::changeToGameMenuSchedule(float delta){
	if(state == GS_GAME_OVER){
		setState(GS_MENU_START);
	}
}